#pragma once

#include<pthread.h>
#include<iostream>
#include"mysql.h"
#include"config_file.h"
#include<ext/hash_map>
#include<ext/hash_set>
#include<stdint.h>


//定义用来保存host的IP/host的port的的集合 数据类型
typedef __gnu_cxx::hash_set<u_int64_t> host_set;
typedef __gnu_cxx::hash_set<u_int64_t>::iterator host_set_it;

//定义用来保存modID/cmdID与host的IP/host的port的对应的关系 数据类型  
typedef __gnu_cxx::hash_map<u_int64_t, host_set> route_map;
typedef __gnu_cxx::hash_map<u_int64_t, host_set>::iterator route_map_it;


// 全局只有一个，单例类，应该将对象静态唯一化
class Route{
public:
    //初始化单例对象
    static void init() {
        //创建单例
        _instance = new Route();
    }
    //获取单例方法
    static Route *instance() {
        //保证init方法在这个进程执行中 只被执行一次
        pthread_once(&_once, init);
        return _instance;
    }

    // 连接数据库的函数
    void connect_db();

    // 构建map数据，将RouteData表中的数据加载到_data_pointer中
    void build_maps();

    // 根据modid和cmdid获取主机的信息集合
    host_set get_hosts(int modid, int cmdid);

    // 得到map中目前已经有的数据
    void test_map();

    // 加载数据版本号
    int load_version();

    // 从mysql中加载最新的数据到_temp_pointer中
    void load_route_data(); 

    //将_temp_pointer的数据更新到_data_pointer
    void swap();

    //加载RouteChange得到修改的modid/cmdid, 将结果放在vector中
    void load_changes(std::vector<uint64_t> &change_list); 

    //删除RouteChange的全部修改记录数据,remove_all为全部删除
    //否则默认删除当前版本之前的全部修改
    void remove_changes(bool remove_all);

private:
    // 全部构造函数私有化，构成单例模式
    Route();
    Route(const Route&);
    const Route& operator=(const Route&);

    // 指向当前单例对象的指针
    static Route * _instance;
    //用于保证创建单例的init方法只执行一次的锁
    static pthread_once_t _once;

    // Mysql数据库句柄
    MYSQL _db_conn;
    char _sql[1000]; //sql语句

    //modid/cmdid---ip/port 对应的route关系map
    route_map* _data_pointer;//指向RouterDataMap_A 当前的关系map
    route_map* _temp_pointer;//指向RouterDataMap_B 当前的关系map
    pthread_rwlock_t _map_lock;

    // 当前的版本号
    long _version;

};


// 用于定期发布已经修改的mod的集合
void* publish_change_mod(void * args);
// 周期行后端检查数据库中的route信息的更改信息
void *check_route_change(void *args);
